package com.christina.engine.execution;

import com.christina.engine.execution.model.ExecutionRequest;
import com.christina.engine.execution.model.ExecutionResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

/**
 * 抽象服务执行器
 * 提供服务执行的通用实现和模板方法
 */
public abstract class AbstractServiceExecutor implements ServiceExecutor {
    
    protected final Logger logger = LoggerFactory.getLogger(getClass());
    
    private final String name;
    private final String[] supportedServiceTypes;
    private final int priority;
    private boolean enabled = true;
    
    protected AbstractServiceExecutor(String name, String[] supportedServiceTypes, int priority) {
        this.name = name;
        this.supportedServiceTypes = supportedServiceTypes != null ? 
                Arrays.copyOf(supportedServiceTypes, supportedServiceTypes.length) : new String[0];
        this.priority = priority;
    }
    
    @Override
    public final ExecutionResult execute(ExecutionRequest request) {
        if (!isEnabled()) {
            logger.debug("Executor {} is disabled, skipping execution", getName());
            return ExecutionResult.failure("Executor is disabled", getName());
        }
        
        if (!supports(request.getServiceType())) {
            logger.debug("Executor {} does not support service type: {}", getName(), request.getServiceType());
            return ExecutionResult.failure("Unsupported service type: " + request.getServiceType(), getName());
        }
        
        logger.debug("Starting execution with {} for service type: {}", getName(), request.getServiceType());
        long startTime = System.currentTimeMillis();
        
        try {
            // 执行前置处理
            preExecute(request);
            
            // 执行核心业务逻辑
            ExecutionResult result = doExecute(request);
            
            // 执行后置处理
            postExecute(request, result);
            
            long executionTime = System.currentTimeMillis() - startTime;
            
            // 更新执行时间和执行器名称
            ExecutionResult finalResult = ExecutionResult.builder()
                    .success(result.isSuccess())
                    .resultData(result.getResultData())
                    .errorMessage(result.getErrorMessage())
                    .exception(result.getException())
                    .metadata(result.getMetadata())
                    .executionDurationMs(executionTime)
                    .executorName(getName())
                    .build();
            
            logger.debug("Completed execution with {} in {}ms, success: {}", 
                    getName(), executionTime, result.isSuccess());
            
            return finalResult;
            
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            logger.error("Error in executor {}: {}", getName(), e.getMessage(), e);
            
            // 执行错误处理
            ExecutionResult errorResult = handleError(request, e);
            
            return ExecutionResult.builder()
                    .success(false)
                    .errorMessage(errorResult.getErrorMessage() != null ? 
                            errorResult.getErrorMessage() : e.getMessage())
                    .exception(e)
                    .executionDurationMs(executionTime)
                    .executorName(getName())
                    .build();
        }
    }
    
    /**
     * 核心执行逻辑，由子类实现
     * 
     * @param request 执行请求
     * @return 执行结果
     */
    protected abstract ExecutionResult doExecute(ExecutionRequest request);
    
    /**
     * 前置处理钩子方法
     * 子类可以重写此方法来执行预处理逻辑
     * 
     * @param request 执行请求
     */
    protected void preExecute(ExecutionRequest request) {
        // 默认实现为空，子类可以重写
    }
    
    /**
     * 后置处理钩子方法
     * 子类可以重写此方法来执行后处理逻辑
     * 
     * @param request 执行请求
     * @param result 执行结果
     */
    protected void postExecute(ExecutionRequest request, ExecutionResult result) {
        // 默认实现为空，子类可以重写
    }
    
    /**
     * 错误处理钩子方法
     * 子类可以重写此方法来自定义错误处理逻辑
     * 
     * @param request 执行请求
     * @param exception 发生的异常
     * @return 错误处理结果
     */
    protected ExecutionResult handleError(ExecutionRequest request, Exception exception) {
        // 默认错误处理：记录错误并返回失败结果
        return ExecutionResult.failure(
                "Error in executor " + getName() + ": " + exception.getMessage(),
                exception,
                getName()
        );
    }
    
    @Override
    public boolean supports(String serviceType) {
        if (serviceType == null || serviceType.trim().isEmpty()) {
            return false;
        }
        
        for (String supportedType : supportedServiceTypes) {
            if (supportedType.equalsIgnoreCase(serviceType.trim())) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    public String getName() {
        return name;
    }
    
    @Override
    public String[] getSupportedServiceTypes() {
        return Arrays.copyOf(supportedServiceTypes, supportedServiceTypes.length);
    }
    
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    
    /**
     * 设置执行器启用状态
     * 
     * @param enabled 是否启用
     */
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    
    @Override
    public int getPriority() {
        return priority;
    }
    
    /**
     * 验证请求参数
     * 
     * @param request 执行请求
     * @param requiredParams 必需的参数名称
     * @throws IllegalArgumentException 如果缺少必需参数
     */
    protected void validateRequiredParameters(ExecutionRequest request, String... requiredParams) {
        for (String param : requiredParams) {
            if (!request.hasParameter(param)) {
                throw new IllegalArgumentException("Missing required parameter: " + param);
            }
        }
    }
    
    /**
     * 获取参数值，如果不存在则返回默认值
     * 
     * @param request 执行请求
     * @param key 参数键
     * @param defaultValue 默认值
     * @param type 参数类型
     * @return 参数值或默认值
     */
    protected <T> T getParameterOrDefault(ExecutionRequest request, String key, T defaultValue, Class<T> type) {
        T value = request.getParameter(key, type);
        return value != null ? value : defaultValue;
    }
    
    @Override
    public String toString() {
        return "AbstractServiceExecutor{" +
                "name='" + name + '\'' +
                ", supportedServiceTypes=" + Arrays.toString(supportedServiceTypes) +
                ", priority=" + priority +
                ", enabled=" + enabled +
                '}';
    }
}